/**
 * http://code.google.com/p/x-updater/
 */
package org.charry.xupdater.configgen;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Arrays;

import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.GnuParser;
import org.apache.commons.cli.HelpFormatter;
import org.apache.commons.cli.MissingArgumentException;
import org.apache.commons.cli.Options;
import org.apache.commons.cli.ParseException;
import org.jdom.Attribute;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.output.Format;
import org.jdom.output.XMLOutputter;

/**
 * 
 * @author WangHui
 *
 */
public class XMLGenerator {
	private Element rootElement;
	private String appPath;
	private String outPath;
	private String indent = "	";
	
	public XMLGenerator() {
		rootElement = new Element("root");
		setOutPath(".");
	}
	
	private void getFilePath(String path) throws IOException{
		File file = new File(path);
		File[] files = file.listFiles();
		
		Arrays.sort(files, new FileComparator());
		
		for(File f: files) {
			Element item = new Element("item");
			// File.getCanonicalPath() may throw an IOException and break out the recursion
			item.setAttribute(new Attribute("path", f.getCanonicalPath().substring(appPath.length()).replace('\\', '/')));
			item.setAttribute(new Attribute("name", f.getName()));
			if(f.isDirectory()) {
				item.setAttribute(new Attribute("hash", ""));
				item.setAttribute(new Attribute("isDir", "true"));
				rootElement.addContent(item);
				getFilePath(f.getPath());
			}
			else if(f.isFile()) {
				item.setAttribute(new Attribute("hash", MD5Util.MD5(f)));
				item.setAttribute(new Attribute("isDir", "false"));
				rootElement.addContent(item);
			}
		}
	}

	public int generate(String[] args) {
		// define options
		Options opts = new Options();
		opts.addOption("dir", true, "Specify the application directory");
		opts.addOption("out", true, "Specify the output directory");
		opts.addOption("ext", true, "Specify an extension");
		opts.addOption("h", false, "help");
		
		GnuParser parser = new GnuParser();
		try {
			CommandLine cmd = parser.parse(opts, args);
			// Rules No.1 arguments must be given in the form of "-key value"
			// Rules No.2 "-dir theDir" has to be given
			if(cmd.getArgList().size() > 0 || !cmd.hasOption("dir") || cmd.hasOption('h')) {
				HelpFormatter hf = new HelpFormatter();
				hf.printHelp("XMLGenerator -dir /opt/var/ -out ~/tmp", opts);
				return -1;
			}

			// set up application home path
			setAppPath(new File(cmd.getOptionValue("dir")).getCanonicalPath());
			// the main part of this program that figures out the whole structure, which deal with recursive
			getFilePath(getAppPath());
			
			if(cmd.hasOption("out")) {
				setOutPath(cmd.getOptionValue("out"));
			} else {
				setOutPath(".");
			}
			if(cmd.hasOption("ext")) {
				// XXX
				System.out.println(cmd.getOptionValue("ext"));
			}
		}
		catch(MissingArgumentException e) {
			System.err.println(e.getMessage());
			return -1;
		}
		catch(ParseException e) {
			System.err.println(e.getMessage());
			return -1;
		}
		catch (IOException e) {
			System.err.println(e.getMessage());
			return -1;
		}
		
		File outPathFolder = new File(getOutPath());
		if(!outPathFolder.exists() && !outPathFolder.mkdirs()) {
			System.err.println("illeagal output path");
			return -1;
		}
		
		File config = new File(outPathFolder, "config.xml");
		Document doc = new Document(getRootElement());

		Format format = Format.getPrettyFormat();
		format.setEncoding("UTF-8");
		format.setIndent(this.indent);
		XMLOutputter out = new XMLOutputter(format);
		try {
			out.output(doc, new FileOutputStream(config));
		} catch (FileNotFoundException e) {
			System.err.println(e.getMessage());
			return -1;
		} catch (IOException e) {
			System.err.println(e.getMessage());
			return -1;
		}
		
		return 0;
	}
	
	public static void main(String[] args) {
		XMLGenerator xmlGenerator = new XMLGenerator();
		if (xmlGenerator.generate(args) == -1) {
			System.exit(-1);
		}
	}
	
	public String getAppPath() {
		return appPath;
	}
	public void setAppPath(String appPath) {
		this.appPath = appPath;
	}
	public String getOutPath() {
		return outPath;
	}
	public void setOutPath(String outPath) {
		this.outPath = outPath;
	}
	public Element getRootElement() {
		return rootElement;
	}
}
